package phase2.rd;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.PrintStream;

import org.junit.Test;

/**
 * 
 * 
 * @author John Girata
 * @version Dec 5, 2012
 */
public class RecursiveDescenderTest {
	@Test
	public void test() throws Exception {
		TokenList tokens = FileReader.getTokens("test/test1.txt");
		RecursiveDescender rd = new RecursiveDescender(tokens);
		Node result = rd.process();
		result.print(new PrintStream(new File("test/output.txt")));
	}
	
	@Test
	public void test0() throws Exception {
		test(0);
	}

	@Test
	public void test1() throws Exception {
		test(1);
	}

	@Test
	public void test2() throws Exception {
		test(2);
	}

	@Test
	public void test3() throws Exception {
		test(3);
	}

	@Test
	public void test4() throws Exception {
		test(4);
	}

	@Test
	public void test5() throws Exception {
		test(5);
	}

	@Test
	public void test6() throws Exception {
		test(6);
	}

	@Test
	public void test7() throws Exception {
		test(7);
	}

	private void test(int num) throws Exception {
		TokenList tokens = FileReader.getTokens("test/test" + num + ".txt");
		RecursiveDescender rd = new RecursiveDescender(tokens);
		rd.process();
	}

	public void testExpTail() {
		TokenList tokens = tokens(key("inters"), key("find"), re("FOO"),
				key("in"), ascii("BAR"), key("union"), key("find"), re("A"),
				key("in"), ascii("B"), key("find2"));
		BinaryNode node = RecursiveDescender.expTail(tokens);

		assertEquals(1, tokens.size());
		assertEquals("find2", tokens.get(0).getValue());

		assertEquals("union", node.getValue());
		assertTrue(node.getLeft() instanceof BinaryNode);

		BinaryNode left = (BinaryNode) node.getLeft();

		assertNull(left.getLeft());
		assertEquals("find", left.getRight().getValue());

		assertTrue(left.getRight() instanceof InteriorNode);

		InteriorNode in = (InteriorNode) left.getRight();
		assertEquals(2, in.getChildren().size());
		assertEquals("FOO", in.getChildren().get(0).getValue());
		assertEquals("BAR", in.getChildren().get(1).getValue());

		assertTrue(node.getRight() instanceof InteriorNode);

		in = (InteriorNode) node.getRight();
		assertEquals(2, in.getChildren().size());
		assertEquals("A", in.getChildren().get(0).getValue());
		assertEquals("B", in.getChildren().get(1).getValue());
	}

	public void testTerm() {
		TokenList tokens = tokens(key("find"), re("FOO"), key("in"),
				ascii("BAR"), key("find2"));
		Node node = RecursiveDescender.term(tokens);

		assertTrue(node instanceof InteriorNode);

		InteriorNode in = (InteriorNode) node;

		assertEquals("find", in.getValue());
		assertEquals(2, in.getChildren().size());

		assertEquals(1, tokens.size());
		assertEquals("find2", tokens.get(0).getValue());
	}

	private TokenList tokens(Token... tokens) {
		TokenList list = new TokenList();

		for (Token t : tokens) {
			list.add(t);
		}

		return list;
	}

	private Token key(String value) {
		return new Token(Token.Type.KEYWORD, value);
	}

	private Token re(String value) {
		return new Token(Token.Type.REGEX, value);
	}

	private Token ascii(String value) {
		return new Token(Token.Type.ASCII, value);
	}
}
